/** Mode handler for a map.
 *@param buffer The buffer to render to.
 *@param map The map to use.
 */
function MapMode(buffer, map)
{
	this.buffer = buffer;
	this._map = map;
	this._map.target = host.screen;
	this._map.xOfs = 0;
	this._map.yOfs = 0;
	dhack.logWindow.pushMessage("%f0Entering level " + map.level);
}
MapMode.prototype =
{
	/** Handle an input action.
	 *@param action The action string to handle.
	 */
	handleAction: function(action)
	{
		switch(action)
		{
			case "up": this._doMove(0, -1); break;
			case "upleft": this._doMove(-1, -1); break;
			case "upright": this._doMove(1, -1); break;
			case "down": this._doMove(0, 1); break;
			case "downleft": this._doMove(-1, 1); break;
			case "downright": this._doMove(1, 1); break;
			case "left": this._doMove(-1, 0); break;
			case "right": this._doMove(1, 0); break;
			case "use":
				// Try to pick up an item
				var ents = this._map.getEntitiesAtPosition(dhack.player.x, dhack.player.y);
				var items = [];
				for(var i = 0; i < ents.length; ++i)
				{
					var ent = ents[i];
					if(ent.isItem)
					{
						items.push(ent);
					}
				}
				if(items.length <= 0)
					break;
				else if(items.length == 1)
				{
					dhack.player.addEntity(items[0]);
					dhack.logWindow.pushMessage("%f0You picked up the " + items[0].name + ".");
					dhack.player.endTurn();
					this._map.doTurn();
					break;
				}
				else
				{
					var options = [];
					for(var i = 0; i < items.length; ++i)
					{
						options.push(items[i].name);
					}
					var listMode = new MenuListMode(
						this.buffer,
						30,
						"%f0Pick up which item?",
						options,
						function(string, source) {
							if(string === null)
								return;
							var item = items[source.selectedIndex];
							dhack.player.addEntity(item);
							dhack.logWindow.pushMessage("%f0You picked up the " + item.name + ".");
							dhack.player.endTurn();
							this._map.doTurn();							
						},
						this,
						false,
						false,
						true
					);
					listMode.__items = items;
					dhack.addModeHandler(listMode);
				}
				break;
			case "inventory":
				dhack.addModeHandler(new InventoryMode(this.buffer));
				return true;
				break;
			case "drop":
			case "throw":
				dhack.addModeHandler(new InventoryMode(this.buffer, action));
				return true;
				break;				
			case "equip":
			case "unequip":
			case "wield":
				dhack.addModeHandler(new InventoryMode(this.buffer, "equip"));
				return true;
				break;				
			case "rest":
				dhack.logWindow.clearMessage();
				dhack.player.endTurn();
				this._map.doTurn();
				break;
			case "look":
				dhack.addModeHandler(
					new SelectPositionMode(
						dhack.map,
						dhack.player.x,
						dhack.player.y,
						0,
						function(x, y, canceled) {},
						this
					)
				);
				break;
			case "ranged":
				if(!dhack.player.equipment.ranged)
				{
					dhack.logWindow.clearMessage();
					dhack.logWindow.pushMessage("%b0You do not have a ranged weapon equiped.");
					break;
				}
				dhack.addModeHandler(
					new SelectPositionMode(
						dhack.map,
						dhack.player.x,
						dhack.player.y,
						dhack.player.range,
						function(x, y, canceled) {
							var ents = this._map.getEntitiesAtPosition(x, y);
							for(var i = ents.length - 1; i >= 0; --i)
							{
								if(ents[i].isMobile)
								{
									dhack.logWindow.clearMessage();
									dhack.player.rangedAttack(ents[i]);
									this._map.doTurn();
									break;
								}
							}
						},
						this)
				);
				break;
			default: return false; break;
		}
		this._doStatusLine();
		return true;
	},
	/** Move the player.
	@param xOfs X offset.
	@param yOfs Y offset.
	*/
	_doMove: function(xOfs, yOfs)
	{
		var nx = dhack.player.x + xOfs;
		var ny = dhack.player.y + yOfs;

		// Handle the player trying to leave the map
		if(nx < 0 ||
			ny < 0 ||
			nx >= this._map.width ||
			ny >= this._map.height)
			return;

		// Normal move
		if(dhack.player.tryMove(xOfs, yOfs))
		{
			dhack.logWindow.clearMessage();
			dhack.player.endTurn();
			this._map.doTurn();
		}
		// Bumped into something
		else
		{
			var ents = this._map.getEntitiesAtPosition(nx, ny);
			for(var i = ents.length - 1; i >= 0; --i)
			{
				if(ents[i].blockWalk)
				{
					dhack.logWindow.clearMessage();
					var ent = ents[i];
					// If it's a mobile attack it
					if(ent.isMobile)
						dhack.player.attack(ent);
					// Otherwise try to use it
					else
						ents[i].use(dhack.player);
					dhack.player.endTurn();
					this._map.doTurn();
					break;
				}
			}
		}
	},
	/** Create the "stuff under me" message if appropriote.
	 */
	_doStatusLine: function()
	{
		if(!dhack.logWindow.isEmpty())
			return;
		var ents = this._map.getEntitiesAtPosition(dhack.player.x, dhack.player.y);
		var desc = "";
		for(var i = 0; i < ents.length; ++i)
		{
			var ent = ents[i];
			if(ent == dhack.player)
				continue;
			if(desc.length > 0)
				desc += ", ";
			desc += ent.name;
		}
		if(desc.length > 0)
			dhack.logWindow.tempMessage("%f0" + desc);
	},
	/** Rerender everything.
	*/
	render: function()
	{
		this._map.render();
	}
};
